// C++ 初识
///////////// namespace、输入输出、缺省参数

// 1.namespace --> 解决命名冲突
#include<iostream>
using namespace std;

#if 0
// 例如求数组中的最小值
int min = INT_MAX;
int a[5] = { 1,2,5,4,0 };
int main()
{
    for(int i = 0; i < 5; i++)
        if(a[i] < min)
            min = a[i];
    cout << min << endl;
    return 0;
}
// 编译i错误，原因：变量min与库里面的重名了


// 引入namespace封装
namespace W
{
    int min = INT_MAX;
} // 不要有分号

int a[5] = { 1,2,5,4,0 };
int main()
{
    for(int i = 0; i < 5; i++)
        if(a[i] < W::min) // 指定访问W里面的min
            W::min = a[i];
    cout << W::min << endl;
    return 0;
}

// 命名空间里可以定义变量、函数、自定义类型、其他命名空间
namespace T
{
    int min;
    void func()
    {
        cout << "void func()" << endl;
    }

    struct Node
    {
        int val;
        Node* next;
    };

    namespace W
    {
        int t;
        int Add(int a, int b)
        {
            return a + b;
        }
    }
}
int main()
{
    // 访问变量
    cout << T::min << endl;
    cout << T::W::t << endl;

    // 使用Node
    T::Node n1;
    // 若用C语言的那套写法：struct Node n2; 需要在Node前加T::，而非struct
    struct T::Node n2;
    return 0;
}

// 上述写法每次访问变量/函数都要加上 命名空间::, 若要频繁使用某个变量/函数，可以使用using语法
namespace W
{
    int a[10]; // 数组a要频繁访问
}

// 展开命名空间, 与展开头文件不同，并非把命名空间里面的内容都拷贝到当前文件，只是声明变量可以去命名空间里找
using namespace W;
// 编译器默认查找顺序：
// 1.当前局部域
// 2.全局域
// 3.展开的命名空间

// 只展开一部分
// using W::a;
int main()
{
    for(int i = 0; i < 10; i++)
        a[i] = i;
    for(int i = 0; i < 10; i++)
        cout << a[i] << ' ';
    return 0;
}

// 展开了多个命名空间, 这些命名空间不可以有重名变量、函数等
namespace W
{
    int a[10]; // 数组a要频繁访问
}
namespace W1
{
    int a;
}
using namespace W;  // W有数组 a
using namespace W1; // W1有整型 a
int main()
{
    cout << a;
    return 0;
}
#endif



#if 0

// // 同名变量会发生冲突
// int a;
// int a;

// 与变量不同，同名的命名空间会合并
namespace T
{
    int min;
    void func()
    {
        cout << "void func()" << endl;
    }
}
namespace T
{
    struct Node
    {
        int val;
        Node* next;
    };

    namespace W
    {
        int t;
        int Add(int a, int b)
        {
            return a + b;
        }
    }
}

int main()
{
    T::func();
    cout << T::W::Add(1, 2) << endl;
    return 0;
}


// 补充：namespace里的变量跟全局变量默认都为0
namespace W
{
    int min;
    int a[10];
}
int main()
{
    cout << W::min << endl;
    for(int i = 0; i < 10; i++)
        cout << W::a[i] << ' ';
    return 0;
}

// 2.输入输出cout cin

int main()
{
    int a = 1;
    double b = 3.14;
    // "<<"不是位运算的左移，是流插入，cout会自动识别类型。
    cout << a << endl; // endl相当于换行, 此代码等价printf("%d\n", a);
    cout << b << endl; // printf("%llf\n", b);
    cout << a << " " << b << endl;  // printf("%d %llf\n", a, b);

    // ">>" 是流提取
    cin >> a >> b; //无需取地址, 此代码等价scanf("%d%llf\n", &a, &b);
    return 0;
}
// 补充：printf/scanf 会比 cout/cin高效一点，因为cout/cin为了兼容C语言的输入输出
// 但是只有输入/输出数据量非常大(比如达到了10^6级别)，才会有明显区别


// 3.缺省参数
// // 比如动态创建数组
// #include<stdlib.h>
// int* get_int_arr(int n)
// {
//     return (int*)malloc(sizeof(int) * n);
// }

// int main()
// {
//     int* a = get_int_arr(5);
//     for(int i = 0; i < 5; i++)
//         a[i] = i;
//     for(int i = 0; i < 5; i++) cout << a[i] << ' ';
//     return 0;
// }

// 若默认创建数组长度都为10，那就可以给个缺省值
int* get_int_arr(int n = 10)
{
    cout << "数组长度:" << n << endl;
    return (int*)malloc(sizeof(int) * n);
}
int main()
{
    int* a = get_int_arr(); // 不传参就用默认的
    for(int i = 0; i < 10; i++) a[i] = i;
    for(int i = 0; i < 10; i++) cout << a[i] << ' ';

    cout << endl;
    int* b = get_int_arr(20); // 传参就用你传的那个
    for(int i = 0; i < 20; i++) b[i] = i;
    for(int i = 0; i < 20; i++) cout << b[i] << ' ';
    return 0;
}


// 缺省值需按照从右往左的顺序给出，不可间断。
void func1(int a, double b = 3.14, int c = 10, char d = 'a')
{
    cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
}

// 错误写法： 形参d还没给缺省值 就给c、b缺省值了
// void func2(int a, double b = 3.14, int c = 10, char d)
// {
//     cout << a << ' ' << b << ' ' << c << d << endl;
// }

int main()
{
    func1(1, 1.2, 20, 'z');
    func1(1, 2.2, 30);
    func1(1, 3.2);
    func1(1);

    return 0;
}

// 若函数定义与声明分离，缺省参数应在函数声明中给，函数定义中不能给

// 函数声明
void func1(int a, double b = 3.14, int c = 10, char d = 'a');

int main()
{
    func1(1, 1.2, 20, 'z');
    func1(1, 2.2, 30);
    func1(1, 3.2);
    func1(1);
    return 0;
}

// 函数定义
void func1(int a, double b, int c, char d)
{
    cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
}
#endif

// 命名空间修正
// 编译器查找规则：
// 1.局部域
// 2.全局域、展开的命名空间 （这两者优先级相同）

namespace W
{
    int a;
}
int a;
using namespace W;

int main()
{
    a = 10;
    return 0;
}